package cn.zkrt.iotms.module.iot.service.impl;

import cn.zkrt.iotms.config.DeviceCategoryConfig;
import cn.zkrt.iotms.module.iot.dao.DeviceBDao;
import cn.zkrt.iotms.module.iot.dao.DeviceTypeBDao;
import cn.zkrt.iotms.module.iot.dto.DeviceBPageDto;
import cn.zkrt.iotms.module.iot.entity.DeviceAttributeB;
import cn.zkrt.iotms.module.iot.entity.DeviceB;
import cn.zkrt.iotms.module.iot.entity.DeviceTypeAttributeB;
import cn.zkrt.iotms.module.iot.entity.DeviceTypeB;
import cn.zkrt.iotms.module.iot.service.*;
import cn.zkrt.iotms.module.iot.vo.*;
import cn.zkrt.iotms.utils.StringUtils;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 设备(DeviceB)表服务实现类
 *
 * @author xulinyu
 * @since 2024-10-06 16:26:30
 */
@Service("deviceBService")
public class DeviceBServiceImpl extends ServiceImpl<DeviceBDao, DeviceB> implements DeviceBService {
    @Resource
    private DeviceBDao deviceBDao;

    private final DeviceTypeAttributeBService deviceTypeAttributeBService;

    private final DeviceAttributeBService deviceAttributeBService;

    private final DeviceTypeBService deviceTypeBService;

    private final DeviceCategoryConfig deviceCategoryConfig;
    @Autowired
    private DeviceTypeBDao deviceTypeBDao;

    public DeviceBServiceImpl(DeviceTypeAttributeBService deviceTypeAttributeBService, DeviceAttributeBService deviceAttributeBService, DeviceCategoryConfig deviceCategoryConfig, DeviceTypeBService deviceTypeBService) {
        this.deviceTypeAttributeBService = deviceTypeAttributeBService;
        this.deviceAttributeBService = deviceAttributeBService;
        this.deviceCategoryConfig = deviceCategoryConfig;
        this.deviceTypeBService = deviceTypeBService;
    }

    @Override
    public Page<DeviceBVO> queryByPage(Page<DeviceBVO> page, String deviceName) {
        return deviceBDao.queryByPage(page, deviceName);
    }

    @Override
    public Boolean add(DeviceB deviceB) {
        //设备名称不能重复
        verifyDuplicate(deviceB);
        //判断有没有设备种类字段传进来
        String deviceCategory = deviceB.getDeviceCategory();
        if(StringUtils.isNotEmpty(deviceCategory)){
            DeviceTypeB deviceTypeB = null;;
            //检查有没有车间、鱼池这两种设备类型（为了动态绑定里面展示未绑定的设备列表，车间、鱼池也需要设备类型）
            LambdaQueryWrapper<DeviceTypeB> w1 = new LambdaQueryWrapper<>();
            w1.eq(DeviceTypeB::getDeviceTypeKey,deviceCategory);
            List<DeviceTypeB> deviceTypeBList = deviceTypeBDao.selectList(w1);
            if(CollectionUtils.isNotEmpty(deviceTypeBList)){
                deviceTypeB = deviceTypeBList.get(0);
            }
            if(Objects.isNull(deviceTypeB)){
                deviceTypeB = new DeviceTypeB();
                //自动添加车间、鱼池的设备类型
                if(deviceCategoryConfig.getCS_CJ().equals(deviceCategory)){
                    deviceTypeB.setDeviceTypeKey(deviceCategoryConfig.getCS_CJ());
                    deviceTypeB.setDeviceTypeName("车间");
                    deviceTypeBService.add(deviceTypeB);
                    //第一次新增车间的时候需要新增增殖站设备,然后将车间的parent_id设置成增殖站设备的ID
                    DeviceB zzz = new DeviceB();
                    zzz.setDeviceCategory(deviceCategoryConfig.getCS_ZZZ());
                    zzz.setStcd(deviceB.getStcd());
                    zzz.setDeviceName(StringUtils.isNotEmpty(deviceB.getStcdName())?deviceB.getStcdName():"默认增殖站");
                    this.add(zzz);
                    deviceB.setParentId(zzz.getId());
                } else if (deviceCategoryConfig.getCS_YC().equals(deviceCategory)) {
                    deviceTypeB.setDeviceTypeKey(deviceCategoryConfig.getCS_YC());
                    deviceTypeB.setDeviceTypeName("鱼池");
                    deviceTypeBService.add(deviceTypeB);
                }
            }
            //如果设备没有指定设备类型ID,就自动赋值
            if(StringUtils.isEmpty(deviceB.getDeviceTypeId())){
                deviceB.setDeviceTypeId(deviceTypeB.getId());
            }
        }
        boolean save = this.save(deviceB);
        //往设备属性表新增设备类型属性关联
        if(StringUtils.isNotEmpty(deviceB.getDeviceTypeId())){
            saveBatchDeviceAttribute(deviceB);
        }
        return save;
    }

    @Override
    public Boolean edit(DeviceB deviceB) {
        //不允许修改设备类型
        deviceB.setDeviceTypeId(null);
        //设备名称不能重复
        verifyDuplicate(deviceB);
        //增殖站不能修改
        deviceB.setStcd(null);
        return this.updateById(deviceB);
    }



    @Override
    public DeviceCategoryTotalVO categoryTotal(String stcd) {
        return deviceBDao.categoryTotal(stcd,deviceCategoryConfig.getCS_CJ(),deviceCategoryConfig.getCS_YC());
    }

    @Override
    public Boolean dynamicBinding(String deviceId, String parentId) {
        DeviceB deviceB = new DeviceB();
        deviceB.setId(deviceId);
        deviceB.setParentId(parentId);
        //todo 校验父子关系胡乱绑定的情况
        return this.updateById(deviceB);
    }

    @Override
    public Page<DeviceBPageVO> sfsPage(Page<DeviceBPageVO> page, DeviceBPageDto dto) {
        return deviceBDao.sfsPage(page,dto,deviceCategoryConfig.getCS_CJ(),deviceCategoryConfig.getCS_YC());
    }

    @Override
    public List<UnbindDeviceVO> unbindList(String stcd) {
        return deviceBDao.unbindList(stcd);
    }

    @Override
    public Boolean unbind(String deviceId) {
        return deviceBDao.unbind(deviceId);
    }

    @Override
    public BindingDeviceVO bindingList(String stcd) {
        BindingDeviceVO vo = new BindingDeviceVO();
        //首先查询跟节点
        LambdaQueryWrapper<DeviceB> w1 = new LambdaQueryWrapper<>();
        w1.eq(DeviceB::getStcd,stcd);
        w1.eq(DeviceB::getDeviceCategory,deviceCategoryConfig.getCS_ZZZ());
        List<DeviceB> list = this.list(w1);
        if(CollectionUtils.isNotEmpty(list)){
            DeviceB one = list.get(0);
            vo.setRootId(one.getId());
        }
        //查询所有绑定的device
        List<BindingDeviceVO.BindingDevice> devices =  deviceBDao.bindingList(stcd);
        List<BindingDeviceVO.DeviceRelationVO> relations = devices.stream().map(x -> {
            BindingDeviceVO.DeviceRelationVO relation = new BindingDeviceVO.DeviceRelationVO();
            relation.setFromId(x.getParentId());
            relation.setToId(x.getId());
            return relation;
        }).collect(Collectors.toList());
        vo.setDevices(devices);
        vo.setRelations(relations);
        return vo;
    }

    @Override
    public Boolean deleteByIds(List<Long> idList) {
        //删除所有关联的设备属性
        LambdaQueryWrapper<DeviceAttributeB> w1 = new LambdaQueryWrapper<>();
        w1.in(DeviceAttributeB::getDeviceId, idList);
        deviceAttributeBService.remove(w1);

        //删除设备
        return this.removeByIds(idList);
    }


    private void verifyDuplicate(DeviceB deviceB) {
        LambdaQueryWrapper<DeviceB> w1 = new LambdaQueryWrapper<>();
        w1.ne(StringUtils.isNotEmpty(deviceB.getId()), DeviceB::getId, deviceB.getId());
        w1.eq(StringUtils.isNotEmpty(deviceB.getStcd()),DeviceB::getStcd,deviceB.getStcd());
        w1.eq(StringUtils.isNotEmpty(deviceB.getDeviceName()),DeviceB::getDeviceName, deviceB.getDeviceName());
        int count = this.count(w1);
        if(count > 0) {
            throw new RuntimeException("设备名称已存在");
        }
    }


    /**
     * 将设备类型属性关联到设备属性
     *
     * @param deviceB
     */
    private void saveBatchDeviceAttribute(DeviceB deviceB) {
        LambdaQueryWrapper<DeviceTypeAttributeB> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotEmpty(deviceB.getDeviceTypeId()), DeviceTypeAttributeB::getDeviceTypeId, deviceB.getDeviceTypeId());
        List<DeviceTypeAttributeB> typeAttrlist = deviceTypeAttributeBService.list(wrapper);
        List<DeviceAttributeB> attrList = Lists.newArrayList();
        typeAttrlist.forEach(x -> {
            DeviceAttributeB deviceAttributeB = new DeviceAttributeB();
            deviceAttributeB.setDeviceId(deviceB.getId());
            deviceAttributeB.setTypeAttributeId(x.getId());
            attrList.add(deviceAttributeB);
        });
        deviceAttributeBService.saveBatch(attrList);
    }
}
